// yl_lidar_io.cpp

#include "yl_lidar_io.h"
#include <cmath>
#include <sstream>
#include <string>

using namespace std;
using namespace boost::gregorian;
using namespace boost::posix_time;

namespace quigon
{
// required fields in para:
// string			"file_ext"
// may add some more for better check.
template<> bool examine_file<YL_Line, YL_Para> (
        const string &filename,
        const YL_Para& para,
        const time_period& target_period
)
{
	try
	{
#ifdef VERBOSE
		cout << "Checking: " << filename << endl;
#endif
		size_t ext_length = para.file_ext.length();
		if (filename.length() < ext_length)
		{
			return false;
		}

		if (filename.substr(filename.length() - ext_length) != para.file_ext)
			return false;

		return true;
	}
	catch (...)
	{
		func_err("examine_file<YL_Line, YL_Para>", filename);
		throw;
	}
}


// required fields in para:
// Time_Serie			"elev_angle"
// even this can be removed for speed, because STK lidar has a fixed elev angle.
static YL_Raw buf; // static means it can only be used in this file.
template<> bool file_to_line<YL_Line, YL_Para> (std::istream &file, YL_Line &line, const YL_Para& para)
{
	try
	{
		file.read(reinterpret_cast<char *>(&buf), sizeof(YL_Raw));

		line.t() = ptime(
		                   date(buf.year, buf.month, buf.day),
		                   time_duration(buf.hours, buf.minutes, buf.seconds, 0)
		           );

		line.duration() = seconds(buf.total_shots / buf.laser_freq) ;

		line["energy"] = buf.energy;
		line["temp_detector"] = buf.temp_detector;
		line["temp_box"] = buf.temp_box;
		line["temp_laser"] = buf.temp_laser;
		line["dtc"] = buf.dtc;
		line["background"] = buf.background;
		line["cbh"] = buf.cbh;

		double bin_time = static_cast<double>(buf.bin_time_ns) * 1.0e-9;
		line["bin_size"] = LIGHT_SPEED * bin_time * 0.5 * 1.0E-3; //in km now
		// May add a check of bin_size here;
		// And other stuffs can be added like this:
		line["sin_elev_angle"] = sin(M_PI / 180.0 * para.elev_angle()[line.t()]);    //sin_elev_angle is Link_Stuff<Time_Serie>
		line["bin_time"] = bin_time;
		line["laser_freq"] = buf.laser_freq;

		int bin_num = static_cast<int>(buf.maxaltitude / line["bin_size"]);

		float* data = new float[bin_num];
		file.read(reinterpret_cast<char *>(data), sizeof(float) * bin_num);

		line.resize(bin_num);
		for (size_t i = 0; i < bin_num; ++i)
		{
			line[i] = data[i];
		}

		delete [] data;

		line.status() = 0 ;
		line.lidar_name() = "YL";

		return true;
	}
	catch (...)
	{
		func_err("file_to_line<YL_Line>");
		throw;
	}
}

}
